package secondriver.jetty.app.server;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.xml.sax.SAXException;

public class JettyAppServer extends Server {

	/**
	 * Applicaton base directory.
	 */
	public static final String PROJECT_HOME = System.getProperty("user.dir");

	/**
	 * Web application default web root directory is '/webapp'.
	 */
	private static final String DEFAULT_WEB_ROOT = PROJECT_HOME + "/webapp";

	/**
	 * Jetty configure file directory is '/webapp/WEB-INF/jetty_etc'.
	 */
	private static final String JETTY_CONFIG_PATH = DEFAULT_WEB_ROOT
			+ "/WEB-INF/jetty_etc";

	/**
	 * Jetty xml file is '/webapp/WEB-INF/jetty_etc/jetty.xml'.
	 */
	private static final String JETTY_XML_CONFIG_PATH = JETTY_CONFIG_PATH
			+ "/jetty.xml";
	/**
	 * Jetty default web.xml file is '/webapp/WEB-INF/jetty_etc/webdefault.xml'.
	 */
	private static final String DEFAULT_WEB_XML_PATH = JETTY_CONFIG_PATH
			+ "/webdefault.xml";

	/**
	 * web application web.xml path is '/webapp/WEB-INF/web.xml'.
	 */
	private static final String WEB_XML_PATH = DEFAULT_WEB_ROOT
			+ "/WEB-INF/web.xml";

	/**
	 * Web application default confetxt path is '/'.
	 */
	private static final String DEFAULT_CONTEXT_PATH = "/";

	private String jettyXmlConfigPath = JETTY_XML_CONFIG_PATH;

	private String defaultWebXmlPath = DEFAULT_WEB_XML_PATH;

	private String contextPath = DEFAULT_CONTEXT_PATH;

	private String webRoot = DEFAULT_WEB_ROOT;

	private String webXmlPath = WEB_XML_PATH;

	public static JettyAppServer getJettyAppServer() {
		return new JettyAppServer(JETTY_XML_CONFIG_PATH, DEFAULT_WEB_XML_PATH,
				DEFAULT_CONTEXT_PATH, DEFAULT_WEB_ROOT, WEB_XML_PATH);
	}

	public static JettyAppServer getJettyAppServer(String contextPath) {
		return new JettyAppServer(JETTY_XML_CONFIG_PATH, DEFAULT_WEB_XML_PATH,
				contextPath, DEFAULT_WEB_ROOT, WEB_XML_PATH);
	}

	public static JettyAppServer getJettyAppServer(String jettyXmlConfigPath,
			String defaultWebXmlPath, String contextPath) {
		return new JettyAppServer(jettyXmlConfigPath, defaultWebXmlPath,
				contextPath, DEFAULT_WEB_ROOT, WEB_XML_PATH);
	}

	public static JettyAppServer getJettyAppServer(String jettyXmlConfigPath,
			String defaultWebXmlPath, String contextPath, String webRoot,
			String webXmlPath) {
		return new JettyAppServer(jettyXmlConfigPath, defaultWebXmlPath,
				contextPath, webRoot, webXmlPath);
	}

	private JettyAppServer(String jettyXmlConfigPath, String defaultWebXmlPath,
			String contextPath, String webRoot, String webXmlPath) {
		super();
		if (this.isNotBlank(jettyXmlConfigPath)) {
			this.jettyXmlConfigPath = jettyXmlConfigPath;
		}
		if (this.isNotBlank(defaultWebXmlPath)) {
			this.defaultWebXmlPath = defaultWebXmlPath;
		}
		if (this.isNotBlank(webRoot)) {
			this.webRoot = webRoot;
		}
		if (this.isNotBlank(webXmlPath)) {
			this.webXmlPath = webXmlPath;
		}
		if (this.isNotBlank(contextPath)) {
			this.contextPath = contextPath;
		}
		this.readXmlConfig();
		this.applyHandler();
	}

	private void applyHandler() {
		ContextHandlerCollection handler = new ContextHandlerCollection();
		WebAppContext webAppContext = new WebAppContext();
		webAppContext.setContextPath(this.contextPath);
		webAppContext.setDefaultsDescriptor(this.defaultWebXmlPath);
		webAppContext.setResourceBase(this.webRoot);
		webAppContext.setDescriptor(this.webXmlPath);
		handler.addHandler(webAppContext);
		super.setHandler(handler);
	}

	private void readXmlConfig() {
		try {
			XmlConfiguration configuration = new XmlConfiguration(
					new FileInputStream(this.jettyXmlConfigPath));
			configuration.configure(this);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private boolean isNotBlank(String object) {
		return null != object && object.trim().length() > 0;
	}

	public void startServer() {
		try {
			super.start();
			while (this.isStarted()) {
				System.out.println("Application " + this.getState() + "...");
				break;
			}
			System.out.println("jetty.xml=" + this.jettyXmlConfigPath);
			System.out.println("webdefault.xml=" + this.defaultWebXmlPath);
			System.out.println("contextPath=" + this.contextPath);
			System.out.println("webRoot=" + this.webRoot);
			System.out.println("webXmlPath=" + this.webXmlPath);
			super.join();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
